# 系统模块包
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import datetime
import sys
import socket
import threading

# 帮我们直接运行此文件时，可以加载到上级目录的ui包
sys.path.append("../")

# 自己定义的模块包
from ui.Ui_net_assist_widget import Ui_NetAssistWidget  #
from common import utils  # 导入通用模块包


class NetAssistWidget(QWidget):
    # 继承父类属性
    def __init__(self, parent=None):
        super().__init__(parent)
        self.ui = Ui_NetAssistWidget()
        self.ui.setupUi(self)

        self.tcp_client = None

        self.init_ui()

    def updata_connect_status(self):
        """
        更新connect连接的文字和图片
        """
        if self.tcp_client is not None:
            self.ui.btn_connect.setText("断开连接(已连接)")
            icon = QIcon()  # 创建icon对象
            icon.addPixmap(QPixmap(":/icon/connect"))
            self.ui.btn_connect.setIcon(icon)
        else:
            self.ui.btn_connect.setText("连接网络")
            icon = QIcon()  # 创建icon对象
            icon.addPixmap(QPixmap(":/icon/disconnect"))
            self.ui.btn_connect.setIcon(icon)

    def run_tcp_client(self, target_ip, target_port):
        # 创建TCP socket对象
        self.tcp_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        try:
            # 连接目标IP和por,建立tcp连接
            addr = (target_ip, int(target_port))
            self.tcp_client.connect(addr)
            print("服务器连接成功")

            # -------------------------------------------更新连接后的ui
            local_ip, local_port = (
                self.tcp_client.getsockname()
            )  # 获取本地分配的ip和端口号
            print("sockname:", local_ip, local_port)

            # 更新本地ip和port
            self.ui.cb_local_ip.setCurrentIndex(self.ui.cb_local_ip.findText(local_ip))
            self.ui.edit_local_port.setText(str(local_port))

            # 修改连接按钮文字和图片
            self.updata_connect_status()

            # ---------------------------------------
            # 循环接收来自服务器的数据，并将数据进行解码
            while True:
                bytes_data = self.tcp_client.recv(2048)
                if bytes_data:
                    bytes_data_msg = utils.decode_data(bytes_data)
                    print(f"bytes_data:{bytes_data_msg}")
                    now_time = datetime.datetime.now()
                    str_data = str(now_time) + ":" + bytes_data_msg
                    self.ui.edit_recieve.append(str_data)  # 将数据打印在接收区
                else:
                    break

        except Exception as e:
            print(e)
        finally:
            print("连接关闭")
            if self.tcp_client is not None:
                self.tcp_client.close()
                self.tcp_client = None
                self.updata_connect_status()

    def handle_client_connect(self):
        """
        客户端连接处理
        """
        if self.tcp_client is not None:
            print("已连接，请断开连接")
            self.tcp_client.close
            self.tcp_client = None
            self.updata_connect_status()
            return

        # 获取输入的目标IP和端口
        target_ip = self.ui.edit_target_ip.text()
        target_port = self.ui.edit_target_port.text()
        print(f"连接服务器:{target_ip}:{target_port}")

        if target_ip == "" or target_port == "":
            print("请输入IP和port")
            return

        tcp_client_thread = threading.Thread(
            target=self.run_tcp_client, args=(target_ip, target_port), daemon=True
        )
        tcp_client_thread.start()

    def handle_new_client(self, tcp_client:socket.socket, client_addr):
        try:
            while True:
                bytes_data = tcp_client.recv(2048)
                if bytes_data:
                    msg = utils.decode_data(bytes_data)
                    self.ui.edit_recieve.append(msg)  # 将接收客户端的内容在接收区显示
                else:
                    # 接收到空字符串，客户端已断开
                    print(f"客户端：{client_addr} 已断开连接")
                    tcp_client.close()
                    break
        except Exception as e:
            print(e)
        finally:
            tcp_client.close()
           
        
    def run_tcp_server(self, server_ip, server_port):
        # 1.创建套接字
        tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 2.绑定本地ip和端口号
        tcp_server.bind((server_ip, int(server_port)))
        # 3. 设置listen被动模式
        tcp_server.listen(128)
        print("-------------------------服务器已开启，等待客户端接入")
        # 等待客户端接入
        try:
            while True:
                tcp_client, client_addr = tcp_server.accept()
                print("有新的客户端接入", client_addr)
                
                thread = threading.Thread(target=self.handle_new_client, args=(tcp_client, client_addr), daemon=True)
                thread.start()
        except Exception as e:
            print(e)
        finally:
            tcp_server.close()
                

    def handle_server_run(self):
        # 获取输入的目标IP和端口
        server_ip = self.ui.edit_target_ip.text()
        server_port = self.ui.edit_target_port.text()
        print(f"开启服务器:{server_ip}:{server_port}")
        if server_port == "":
            print("请输入端口号")
            return
        # 1 创建套接字
        tcp_server_thread = threading.Thread(
            target=self.run_tcp_server, args=(server_ip, server_port), daemon=True
        )
        tcp_server_thread.start()

    def on_connect_click(self):
        """
        连接
        """
        current_mode = self.ui.cb_mode.currentIndex()
        if current_mode == 1:
            self.handle_client_connect()
        elif current_mode == 0:
            self.handle_server_run()

    def on_send_click(self):
        """
        发送数据
        """
        # 判断是否连接
        if self.tcp_client is None:
            print("请先连接")
            QMessageBox.warning(self, "警告", "请先连接设备")
            return
        # 取出发送区的数据
        text = self.ui.edit_send.toPlainText()
        self.tcp_client.send(text.encode("UTF-8"))

    def on_mode_changed(self):
        """
        模式切换后的文本内容变换
        """
        # 打印当前模式
        print("当前模式", self.ui.cb_mode.currentIndex())

        mode_index = self.ui.cb_mode.currentIndex()
        if mode_index == 1:  # 客户端模式
            self.ui.label_ip.setText("服务器ip")
            self.ui.label_port.setText("服务器端口")
            self.ui.label_local_port.show()
            self.ui.edit_local_port.show()
        elif mode_index == 0:  # 服务器模式
            self.ui.label_ip.setText("本地ip")
            self.ui.label_port.setText("本地端口")
            self.ui.label_local_port.hide()
            self.ui.edit_local_port.hide()
        else:  # UDP模式
            pass

    # -----------------------------------------------------------------
    def init_ui(self):
        self.ui.edit_target_ip.setText("127.0.0.1")
        self.ui.edit_target_port.setText("8888")
        # 将获取的所有本地IP添加到cb_local_ip的条目中
        local_ips = utils.get_local_ip()
        self.ui.cb_local_ip.addItems(local_ips)
        self.ui.btn_connect.clicked.connect(self.on_connect_click)
        self.ui.btn_send.clicked.connect(self.on_send_click)

        self.ui.cb_mode.currentIndexChanged.connect(self.on_mode_changed)


if __name__ == "__main__":
    app = QApplication(sys.argv)

    window = NetAssistWidget()
    window.show()

    sys.exit(app.exec_())
